package de.dhbw.karlsruhe.picsim.model.memory.impl;

import de.dhbw.karlsruhe.picsim.model.memory.OpCode;
import de.dhbw.karlsruhe.picsim.util.Bits;
import de.dhbw.karlsruhe.picsim.util.impl.BitUtilities;
import de.dhbw.karlsruhe.picsim.util.impl.Lengths;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

public final class OpCodeImpl implements OpCode {
    private static final Log log = LogFactory.getLog(OpCodeImpl.class);
    private final Bits value;


    @Nullable
    public static OpCode createOpCode(final int intValue) {
        return createOpCode(BitUtilities.asLeastSignificantBitFirst(intValue, Lengths.OPCODE_LENGTH));
    }

    @Nullable
    private static OpCode createOpCode(@NotNull final Bits bits) {
        if (bits.getLength() != Lengths.OPCODE_LENGTH) {
            log.warn("Illegal argument " + bits);
            return null;
        }
        return new OpCodeImpl(bits);
    }


    private OpCodeImpl(final Bits value) {
        this.value = value;
    }

    @NotNull
    @Override
    public Bits getValue() {
        return value;
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder();
        sb.append("de.dhbw.karlsruhe.picsim.model.memory.impl.OpCodeImpl");
        sb.append("{value=").append(value);
        sb.append('}');
        return sb.toString();
    }

    @SuppressWarnings({"SimplifiableIfStatement", "CastToConcreteClass", "AccessingNonPublicFieldOfAnotherObject"})
    @Override
    public boolean equals(final Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null || getClass() != obj.getClass()) {
            return false;
        }
        return value.equals(((OpCodeImpl) obj).value);
    }

    @Override
    public int hashCode() {
        return value.hashCode();
    }
}
